#include "../../include/LRUCache.h"
//log
#include "../../include/Logger.h"
#include <fstream>
#include <sstream>

LRUCache::LRUCache(int num)
:_resultsMap()
,_resultsList()
,_pendingUpdateMap()
,_pendingUpdateList()
,_capacity(num)
{

}

LRUCache::LRUCache(const LRUCache & cache)
:_resultsMap(cache._resultsMap)
,_resultsList(cache._resultsList)
,_pendingUpdateMap(cache._pendingUpdateMap)
,_pendingUpdateList(cache._pendingUpdateList)
,_capacity(cache._capacity)
{

}

string LRUCache::SearchKeyword(const string &key) // 在缓存中查找关键字
{
    cout << key << endl;
    auto it = _resultsMap.find(key);
    if(it == _resultsMap.end()){
        return string();
    }
    else{
        _resultsList.splice(_resultsList.begin(), _resultsList, it->second);
        string ret = it->second->value;
        addPendingList(key, ret);
        return ret;
    }
}

void LRUCache::clearPendingList() //清空待更新队列
{
    _pendingUpdateList.clear();
    _pendingUpdateMap.clear();
}

void LRUCache::addPendingList(const string& key,const string & value)//往缓存中添加数据
{
    auto it = _pendingUpdateMap.find(key);
    if(it != _pendingUpdateMap.end()){ //如果key已经存在
        it->second->value = value; //更新key对应的value
        _pendingUpdateList.splice(_pendingUpdateList.begin(), _pendingUpdateList, it->second); //将数据放到链表头
    }
    else{ //如果key不存在
        if(_capacity == (int)_pendingUpdateList.size()){ 
            //链表已满
            auto & delNode = _pendingUpdateList.back();
            _pendingUpdateMap.erase(delNode.key); //在哈希表中删除
            _pendingUpdateList.pop_back(); //删除表尾元素
        }
        //不论满还是不满，直接在链表前面插入并插入到unordered_map中
        _pendingUpdateList.push_front(CacheNode(key, value));
        _pendingUpdateMap.insert(std::make_pair(key, _pendingUpdateList.begin()));
        //cout << "插入(" << key << "," << value << ")" << endl;
    }
}

void LRUCache::addResultList(const string& key,const string & value)//往缓存中添加数据
{
    auto it = _resultsMap.find(key);
    if(it != _resultsMap.end()){ //如果key已经存在
        it->second->value = value; //更新key对应的value
        _resultsList.splice(_resultsList.begin(), _resultsList, it->second); //将数据放到链表头
    }
    else{ //如果key不存在
        if(_capacity == (int)_resultsList.size()){ 
            //链表已满
            auto & delNode = _resultsList.back();
            _resultsMap.erase(delNode.key); //在哈希表中删除
            _resultsList.pop_back(); //删除表尾元素
        }
        //不论满还是不满，直接在链表前面插入并插入到unordered_map中
        _resultsList.push_front(CacheNode(key, value));
        _resultsMap.insert(std::make_pair(key, _resultsList.begin()));
        //cout << "插入(" << key << "," << value << ")" << endl;
    }
}

void LRUCache::readFromFile(const string& filename)//从文件中读取缓存信息
{
    ifstream ifs(filename);
    if(!ifs.is_open()){
        //log
        LogError("open %s fail!", filename.c_str());
        return;
    }
    LogInfo("read: %s", filename.c_str());
    string line;
    while(getline(ifs,line)){
        istringstream iss(line);
        string key;
        string value;
        if(!iss.good()){
            LogError("fail!");
        }

        std::getline(iss, key, ' ');
        std::getline(iss, value);
        
        _resultsList.push_front(CacheNode(key, value));
        _resultsMap.insert(make_pair(key, _resultsList.begin()));
    }
    ifs.close();
}

void LRUCache::writeToFile(const string& filename)//将缓存信息写入到文件中
{
    ofstream ofs(filename);
    if(!ofs.good()){
        //log
        LogError("open %s fail!", filename.c_str());
        return;
    }

    for(auto & elem : _resultsList){
        ofs << elem.key << " " << elem.value << endl;
        //cout <<  "写入 " << elem.key << " " << elem.value << endl;
    }
    //cout << "写入缓存文件" << endl;
    LogInfo("写入缓存文件");
    ofs.close();
}

void LRUCache::update(LRUCache &rhs)// 更新缓存信息
{
    auto tmp = rhs.getPendingUpateList();
    for(auto & elem : tmp){
        //cout << elem.key << " " << elem.value << endl;
        addResultList(elem.key, elem.value);
    }
}

void LRUCache::updateAll(LRUCache &rhs)// 更新缓存信息
{
    auto tmp = rhs.getresultsList();
    for(auto & elem : tmp){
        addResultList(elem.key, elem.value);
    }
}

list<CacheNode> &LRUCache::getPendingUpateList() //获取待更新的节点List
{
    return _pendingUpdateList;
}

list<CacheNode> &LRUCache::getresultsList()
{
    return _resultsList;
}

void LRUCache::printResultList()//测试用
{
    if(_resultsList.empty()){
        cout << "_resultsList is empty!" << endl;
    }
    for(auto & elem : _resultsList){
        cout << "(" << elem.key << "," << elem.value << ")" << endl;
    }
}

void LRUCache::printPendingList()//测试用
{
    if(_pendingUpdateList.empty()){
        cout << "_pendingUpdateList is empty!" << endl;
    }
    for(auto & elem : _pendingUpdateList){
        cout << "(" << elem.key << "," << elem.value << ")" << endl;
    }
}
